home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2009 February / PCWFEB09.iso / Software / Linux / Kubuntu 8.10 / kubuntu-8.10-desktop-i386.iso / casper / filesystem.squashfs / usr / lib / python2.5 / cgi.pyc (.txt) < prev    next >
Python Compiled Bytecode  |  2008-10-29  |  33KB  |  1,167 lines

  1. # Source Generated with Decompyle++
  2. # File: in.pyc (Python 2.5)
  3.  
  4. '''Support module for CGI (Common Gateway Interface) scripts.
  5.  
  6. This module defines a number of utilities for use by CGI scripts
  7. written in Python.
  8. '''
  9. __version__ = '2.6'
  10. from operator import attrgetter
  11. import sys
  12. import os
  13. import urllib
  14. import mimetools
  15. import rfc822
  16. import UserDict
  17.  
  18. try:
  19.     from cStringIO import StringIO
  20. except ImportError:
  21.     from StringIO import StringIO
  22.  
  23. __all__ = [
  24.     'MiniFieldStorage',
  25.     'FieldStorage',
  26.     'FormContentDict',
  27.     'SvFormContentDict',
  28.     'InterpFormContentDict',
  29.     'FormContent',
  30.     'parse',
  31.     'parse_qs',
  32.     'parse_qsl',
  33.     'parse_multipart',
  34.     'parse_header',
  35.     'print_exception',
  36.     'print_environ',
  37.     'print_form',
  38.     'print_directory',
  39.     'print_arguments',
  40.     'print_environ_usage',
  41.     'escape']
  42. logfile = ''
  43. logfp = None
  44.  
  45. def initlog(*allargs):
  46.     '''Write a log message, if there is a log file.
  47.  
  48.     Even though this function is called initlog(), you should always
  49.     use log(); log is a variable that is set either to initlog
  50.     (initially), to dolog (once the log file has been opened), or to
  51.     nolog (when logging is disabled).
  52.  
  53.     The first argument is a format string; the remaining arguments (if
  54.     any) are arguments to the % operator, so e.g.
  55.         log("%s: %s", "a", "b")
  56.     will write "a: b" to the log file, followed by a newline.
  57.  
  58.     If the global logfp is not None, it should be a file object to
  59.     which log data is written.
  60.  
  61.     If the global logfp is None, the global logfile may be a string
  62.     giving a filename to open, in append mode.  This file should be
  63.     world writable!!!  If the file can\'t be opened, logging is
  64.     silently disabled (since there is no safe place where we could
  65.     send an error message).
  66.  
  67.     '''
  68.     global logfp, log
  69.     if logfile and not logfp:
  70.         
  71.         try:
  72.             logfp = open(logfile, 'a')
  73.         except IOError:
  74.             pass
  75.         except:
  76.             None<EXCEPTION MATCH>IOError
  77.         
  78.  
  79.     None<EXCEPTION MATCH>IOError
  80.     if not logfp:
  81.         log = nolog
  82.     else:
  83.         log = dolog
  84.     log(*allargs)
  85.  
  86.  
  87. def dolog(fmt, *args):
  88.     '''Write a log message to the log file.  See initlog() for docs.'''
  89.     logfp.write(fmt % args + '\n')
  90.  
  91.  
  92. def nolog(*allargs):
  93.     '''Dummy function, assigned to log when logging is disabled.'''
  94.     pass
  95.  
  96. log = initlog
  97. maxlen = 0
  98.  
  99. def parse(fp = None, environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  100.     '''Parse a query in the environment or from a file (default stdin)
  101.  
  102.         Arguments, all optional:
  103.  
  104.         fp              : file pointer; default: sys.stdin
  105.  
  106.         environ         : environment dictionary; default: os.environ
  107.  
  108.         keep_blank_values: flag indicating whether blank values in
  109.             URL encoded forms should be treated as blank strings.
  110.             A true value indicates that blanks should be retained as
  111.             blank strings.  The default false value indicates that
  112.             blank values are to be ignored and treated as if they were
  113.             not included.
  114.  
  115.         strict_parsing: flag indicating what to do with parsing errors.
  116.             If false (the default), errors are silently ignored.
  117.             If true, errors raise a ValueError exception.
  118.     '''
  119.     if fp is None:
  120.         fp = sys.stdin
  121.     
  122.     if 'REQUEST_METHOD' not in environ:
  123.         environ['REQUEST_METHOD'] = 'GET'
  124.     
  125.     if environ['REQUEST_METHOD'] == 'POST':
  126.         (ctype, pdict) = parse_header(environ['CONTENT_TYPE'])
  127.         if ctype == 'multipart/form-data':
  128.             return parse_multipart(fp, pdict)
  129.         elif ctype == 'application/x-www-form-urlencoded':
  130.             clength = int(environ['CONTENT_LENGTH'])
  131.             if maxlen and clength > maxlen:
  132.                 raise ValueError, 'Maximum content length exceeded'
  133.             
  134.             qs = fp.read(clength)
  135.         else:
  136.             qs = ''
  137.         if 'QUERY_STRING' in environ:
  138.             if qs:
  139.                 qs = qs + '&'
  140.             
  141.             qs = qs + environ['QUERY_STRING']
  142.         elif sys.argv[1:]:
  143.             if qs:
  144.                 qs = qs + '&'
  145.             
  146.             qs = qs + sys.argv[1]
  147.         
  148.         environ['QUERY_STRING'] = qs
  149.     elif 'QUERY_STRING' in environ:
  150.         qs = environ['QUERY_STRING']
  151.     elif sys.argv[1:]:
  152.         qs = sys.argv[1]
  153.     else:
  154.         qs = ''
  155.     environ['QUERY_STRING'] = qs
  156.     return parse_qs(qs, keep_blank_values, strict_parsing)
  157.  
  158.  
  159. def parse_qs(qs, keep_blank_values = 0, strict_parsing = 0):
  160.     '''Parse a query given as a string argument.
  161.  
  162.         Arguments:
  163.  
  164.         qs: URL-encoded query string to be parsed
  165.  
  166.         keep_blank_values: flag indicating whether blank values in
  167.             URL encoded queries should be treated as blank strings.
  168.             A true value indicates that blanks should be retained as
  169.             blank strings.  The default false value indicates that
  170.             blank values are to be ignored and treated as if they were
  171.             not included.
  172.  
  173.         strict_parsing: flag indicating what to do with parsing errors.
  174.             If false (the default), errors are silently ignored.
  175.             If true, errors raise a ValueError exception.
  176.     '''
  177.     dict = { }
  178.     for name, value in parse_qsl(qs, keep_blank_values, strict_parsing):
  179.         if name in dict:
  180.             dict[name].append(value)
  181.             continue
  182.         dict[name] = [
  183.             value]
  184.     
  185.     return dict
  186.  
  187.  
  188. def parse_qsl(qs, keep_blank_values = 0, strict_parsing = 0):
  189.     '''Parse a query given as a string argument.
  190.  
  191.     Arguments:
  192.  
  193.     qs: URL-encoded query string to be parsed
  194.  
  195.     keep_blank_values: flag indicating whether blank values in
  196.         URL encoded queries should be treated as blank strings.  A
  197.         true value indicates that blanks should be retained as blank
  198.         strings.  The default false value indicates that blank values
  199.         are to be ignored and treated as if they were  not included.
  200.  
  201.     strict_parsing: flag indicating what to do with parsing errors. If
  202.         false (the default), errors are silently ignored. If true,
  203.         errors raise a ValueError exception.
  204.  
  205.     Returns a list, as G-d intended.
  206.     '''
  207.     pairs = [ s2 for s1 in qs.split('&') for s2 in s1.split(';') ]
  208.     r = []
  209.     for name_value in pairs:
  210.         nv = name_value.split('=', 1)
  211.         if len(nv) != 2:
  212.             if strict_parsing:
  213.                 raise ValueError, 'bad query field: %r' % (name_value,)
  214.             
  215.             if keep_blank_values:
  216.                 nv.append('')
  217.             
  218.         
  219.         if len(nv[1]) or keep_blank_values:
  220.             name = urllib.unquote(nv[0].replace('+', ' '))
  221.             value = urllib.unquote(nv[1].replace('+', ' '))
  222.             r.append((name, value))
  223.             continue
  224.     
  225.     return r
  226.  
  227.  
  228. def parse_multipart(fp, pdict):
  229.     '''Parse multipart input.
  230.  
  231.     Arguments:
  232.     fp   : input file
  233.     pdict: dictionary containing other parameters of content-type header
  234.  
  235.     Returns a dictionary just like parse_qs(): keys are the field names, each
  236.     value is a list of values for that field.  This is easy to use but not
  237.     much good if you are expecting megabytes to be uploaded -- in that case,
  238.     use the FieldStorage class instead which is much more flexible.  Note
  239.     that content-type is the raw, unparsed contents of the content-type
  240.     header.
  241.  
  242.     XXX This does not parse nested multipart parts -- use FieldStorage for
  243.     that.
  244.  
  245.     XXX This should really be subsumed by FieldStorage altogether -- no
  246.     point in having two implementations of the same parsing algorithm.
  247.     Also, FieldStorage protects itself better against certain DoS attacks
  248.     by limiting the size of the data read in one chunk.  The API here
  249.     does not support that kind of protection.  This also affects parse()
  250.     since it can call parse_multipart().
  251.  
  252.     '''
  253.     boundary = ''
  254.     if 'boundary' in pdict:
  255.         boundary = pdict['boundary']
  256.     
  257.     if not valid_boundary(boundary):
  258.         raise ValueError, 'Invalid boundary in multipart form: %r' % (boundary,)
  259.     
  260.     nextpart = '--' + boundary
  261.     lastpart = '--' + boundary + '--'
  262.     partdict = { }
  263.     terminator = ''
  264.     while terminator != lastpart:
  265.         bytes = -1
  266.         data = None
  267.         if terminator:
  268.             headers = mimetools.Message(fp)
  269.             clength = headers.getheader('content-length')
  270.             if clength:
  271.                 
  272.                 try:
  273.                     bytes = int(clength)
  274.                 except ValueError:
  275.                     pass
  276.                 except:
  277.                     None<EXCEPTION MATCH>ValueError
  278.                 
  279.  
  280.             None<EXCEPTION MATCH>ValueError
  281.             if bytes > 0:
  282.                 if maxlen and bytes > maxlen:
  283.                     raise ValueError, 'Maximum content length exceeded'
  284.                 
  285.                 data = fp.read(bytes)
  286.             else:
  287.                 data = ''
  288.         
  289.         lines = []
  290.         while None:
  291.             line = fp.readline()
  292.             if not line:
  293.                 terminator = lastpart
  294.                 break
  295.             
  296.             if line[:2] == '--':
  297.                 terminator = line.strip()
  298.                 if terminator in (nextpart, lastpart):
  299.                     break
  300.                 
  301.             
  302.             continue
  303.             if data is None:
  304.                 continue
  305.             
  306.         if bytes < 0:
  307.             if lines:
  308.                 line = lines[-1]
  309.                 if line[-2:] == '\r\n':
  310.                     line = line[:-2]
  311.                 elif line[-1:] == '\n':
  312.                     line = line[:-1]
  313.                 
  314.                 lines[-1] = line
  315.                 data = ''.join(lines)
  316.             
  317.         
  318.         line = headers['content-disposition']
  319.         if not line:
  320.             continue
  321.         
  322.         (key, params) = parse_header(line)
  323.         if key != 'form-data':
  324.             continue
  325.         
  326.         if 'name' in params:
  327.             name = params['name']
  328.         
  329.         if name in partdict:
  330.             partdict[name].append(data)
  331.             continue
  332.         'name' in params
  333.         partdict[name] = [
  334.             data]
  335.     return partdict
  336.  
  337.  
  338. def parse_header(line):
  339.     '''Parse a Content-type like header.
  340.  
  341.     Return the main content-type and a dictionary of options.
  342.  
  343.     '''
  344.     plist = [ x.strip() for x in line.split(';') ]
  345.     key = plist.pop(0).lower()
  346.     pdict = { }
  347.     for p in plist:
  348.         i = p.find('=')
  349.         if i >= 0:
  350.             name = p[:i].strip().lower()
  351.             value = p[i + 1:].strip()
  352.             if len(value) >= 2:
  353.                 if value[-1] == value[-1]:
  354.                     pass
  355.                 elif value[-1] == '"':
  356.                     value = value[1:-1]
  357.                     value = value.replace('\\\\', '\\').replace('\\"', '"')
  358.                 
  359.             pdict[name] = value
  360.             continue
  361.         []
  362.     
  363.     return (key, pdict)
  364.  
  365.  
  366. class MiniFieldStorage:
  367.     '''Like FieldStorage, for use when no file uploads are possible.'''
  368.     filename = None
  369.     list = None
  370.     type = None
  371.     file = None
  372.     type_options = { }
  373.     disposition = None
  374.     disposition_options = { }
  375.     headers = { }
  376.     
  377.     def __init__(self, name, value):
  378.         '''Constructor from field name and value.'''
  379.         self.name = name
  380.         self.value = value
  381.  
  382.     
  383.     def __repr__(self):
  384.         '''Return printable representation.'''
  385.         return 'MiniFieldStorage(%r, %r)' % (self.name, self.value)
  386.  
  387.  
  388.  
  389. class FieldStorage:
  390.     """Store a sequence of fields, reading multipart/form-data.
  391.  
  392.     This class provides naming, typing, files stored on disk, and
  393.     more.  At the top level, it is accessible like a dictionary, whose
  394.     keys are the field names.  (Note: None can occur as a field name.)
  395.     The items are either a Python list (if there's multiple values) or
  396.     another FieldStorage or MiniFieldStorage object.  If it's a single
  397.     object, it has the following attributes:
  398.  
  399.     name: the field name, if specified; otherwise None
  400.  
  401.     filename: the filename, if specified; otherwise None; this is the
  402.         client side filename, *not* the file name on which it is
  403.         stored (that's a temporary file you don't deal with)
  404.  
  405.     value: the value as a *string*; for file uploads, this
  406.         transparently reads the file every time you request the value
  407.  
  408.     file: the file(-like) object from which you can read the data;
  409.         None if the data is stored a simple string
  410.  
  411.     type: the content-type, or None if not specified
  412.  
  413.     type_options: dictionary of options specified on the content-type
  414.         line
  415.  
  416.     disposition: content-disposition, or None if not specified
  417.  
  418.     disposition_options: dictionary of corresponding options
  419.  
  420.     headers: a dictionary(-like) object (sometimes rfc822.Message or a
  421.         subclass thereof) containing *all* headers
  422.  
  423.     The class is subclassable, mostly for the purpose of overriding
  424.     the make_file() method, which is called internally to come up with
  425.     a file open for reading and writing.  This makes it possible to
  426.     override the default choice of storing all files in a temporary
  427.     directory and unlinking them as soon as they have been opened.
  428.  
  429.     """
  430.     
  431.     def __init__(self, fp = None, headers = None, outerboundary = '', environ = os.environ, keep_blank_values = 0, strict_parsing = 0):
  432.         '''Constructor.  Read multipart/* until last part.
  433.  
  434.         Arguments, all optional:
  435.  
  436.         fp              : file pointer; default: sys.stdin
  437.             (not used when the request method is GET)
  438.  
  439.         headers         : header dictionary-like object; default:
  440.             taken from environ as per CGI spec
  441.  
  442.         outerboundary   : terminating multipart boundary
  443.             (for internal use only)
  444.  
  445.         environ         : environment dictionary; default: os.environ
  446.  
  447.         keep_blank_values: flag indicating whether blank values in
  448.             URL encoded forms should be treated as blank strings.
  449.             A true value indicates that blanks should be retained as
  450.             blank strings.  The default false value indicates that
  451.             blank values are to be ignored and treated as if they were
  452.             not included.
  453.  
  454.         strict_parsing: flag indicating what to do with parsing errors.
  455.             If false (the default), errors are silently ignored.
  456.             If true, errors raise a ValueError exception.
  457.  
  458.         '''
  459.         method = 'GET'
  460.         self.keep_blank_values = keep_blank_values
  461.         self.strict_parsing = strict_parsing
  462.         if 'REQUEST_METHOD' in environ:
  463.             method = environ['REQUEST_METHOD'].upper()
  464.         
  465.         if method == 'GET' or method == 'HEAD':
  466.             if 'QUERY_STRING' in environ:
  467.                 qs = environ['QUERY_STRING']
  468.             elif sys.argv[1:]:
  469.                 qs = sys.argv[1]
  470.             else:
  471.                 qs = ''
  472.             fp = StringIO(qs)
  473.             if headers is None:
  474.                 headers = {
  475.                     'content-type': 'application/x-www-form-urlencoded' }
  476.             
  477.         
  478.         if headers is None:
  479.             headers = { }
  480.             if method == 'POST':
  481.                 headers['content-type'] = 'application/x-www-form-urlencoded'
  482.             
  483.             if 'CONTENT_TYPE' in environ:
  484.                 headers['content-type'] = environ['CONTENT_TYPE']
  485.             
  486.             if 'CONTENT_LENGTH' in environ:
  487.                 headers['content-length'] = environ['CONTENT_LENGTH']
  488.             
  489.         
  490.         if not fp:
  491.             pass
  492.         self.fp = sys.stdin
  493.         self.headers = headers
  494.         self.outerboundary = outerboundary
  495.         cdisp = ''
  496.         pdict = { }
  497.         if 'content-disposition' in self.headers:
  498.             (cdisp, pdict) = parse_header(self.headers['content-disposition'])
  499.         
  500.         self.disposition = cdisp
  501.         self.disposition_options = pdict
  502.         self.name = None
  503.         if 'name' in pdict:
  504.             self.name = pdict['name']
  505.         
  506.         self.filename = None
  507.         if 'filename' in pdict:
  508.             self.filename = pdict['filename']
  509.         
  510.         if 'content-type' in self.headers:
  511.             (ctype, pdict) = parse_header(self.headers['content-type'])
  512.         elif self.outerboundary or method != 'POST':
  513.             ctype = 'text/plain'
  514.             pdict = { }
  515.         else:
  516.             ctype = 'application/x-www-form-urlencoded'
  517.             pdict = { }
  518.         self.type = ctype
  519.         self.type_options = pdict
  520.         self.innerboundary = ''
  521.         if 'boundary' in pdict:
  522.             self.innerboundary = pdict['boundary']
  523.         
  524.         clen = -1
  525.         if 'content-length' in self.headers:
  526.             
  527.             try:
  528.                 clen = int(self.headers['content-length'])
  529.             except ValueError:
  530.                 pass
  531.  
  532.             if maxlen and clen > maxlen:
  533.                 raise ValueError, 'Maximum content length exceeded'
  534.             
  535.         
  536.         self.length = clen
  537.         self.list = None
  538.         self.file = None
  539.         self.done = 0
  540.         if ctype == 'application/x-www-form-urlencoded':
  541.             self.read_urlencoded()
  542.         elif ctype[:10] == 'multipart/':
  543.             self.read_multi(environ, keep_blank_values, strict_parsing)
  544.         else:
  545.             self.read_single()
  546.  
  547.     
  548.     def __repr__(self):
  549.         '''Return a printable representation.'''
  550.         return 'FieldStorage(%r, %r, %r)' % (self.name, self.filename, self.value)
  551.  
  552.     
  553.     def __iter__(self):
  554.         return iter(self.keys())
  555.  
  556.     
  557.     def __getattr__(self, name):
  558.         if name != 'value':
  559.             raise AttributeError, name
  560.         
  561.         if self.file:
  562.             self.file.seek(0)
  563.             value = self.file.read()
  564.             self.file.seek(0)
  565.         elif self.list is not None:
  566.             value = self.list
  567.         else:
  568.             value = None
  569.         return value
  570.  
  571.     
  572.     def __getitem__(self, key):
  573.         '''Dictionary style indexing.'''
  574.         if self.list is None:
  575.             raise TypeError, 'not indexable'
  576.         
  577.         found = []
  578.         for item in self.list:
  579.             if item.name == key:
  580.                 found.append(item)
  581.                 continue
  582.         
  583.         if not found:
  584.             raise KeyError, key
  585.         
  586.         if len(found) == 1:
  587.             return found[0]
  588.         else:
  589.             return found
  590.  
  591.     
  592.     def getvalue(self, key, default = None):
  593.         """Dictionary style get() method, including 'value' lookup."""
  594.         if key in self:
  595.             value = self[key]
  596.             if type(value) is type([]):
  597.                 return map(attrgetter('value'), value)
  598.             else:
  599.                 return value.value
  600.         else:
  601.             return default
  602.  
  603.     
  604.     def getfirst(self, key, default = None):
  605.         ''' Return the first value received.'''
  606.         if key in self:
  607.             value = self[key]
  608.             if type(value) is type([]):
  609.                 return value[0].value
  610.             else:
  611.                 return value.value
  612.         else:
  613.             return default
  614.  
  615.     
  616.     def getlist(self, key):
  617.         ''' Return list of received values.'''
  618.         if key in self:
  619.             value = self[key]
  620.             if type(value) is type([]):
  621.                 return map(attrgetter('value'), value)
  622.             else:
  623.                 return [
  624.                     value.value]
  625.         else:
  626.             return []
  627.  
  628.     
  629.     def keys(self):
  630.         '''Dictionary style keys() method.'''
  631.         if self.list is None:
  632.             raise TypeError, 'not indexable'
  633.         
  634.         keys = []
  635.         for item in self.list:
  636.             if item.name not in keys:
  637.                 keys.append(item.name)
  638.                 continue
  639.         
  640.         return keys
  641.  
  642.     
  643.     def has_key(self, key):
  644.         '''Dictionary style has_key() method.'''
  645.         if self.list is None:
  646.             raise TypeError, 'not indexable'
  647.         
  648.         for item in self.list:
  649.             if item.name == key:
  650.                 return True
  651.                 continue
  652.         
  653.         return False
  654.  
  655.     
  656.     def __contains__(self, key):
  657.         '''Dictionary style __contains__ method.'''
  658.         if self.list is None:
  659.             raise TypeError, 'not indexable'
  660.         
  661.         for item in self.list:
  662.             if item.name == key:
  663.                 return True
  664.                 continue
  665.         
  666.         return False
  667.  
  668.     
  669.     def __len__(self):
  670.         '''Dictionary style len(x) support.'''
  671.         return len(self.keys())
  672.  
  673.     
  674.     def read_urlencoded(self):
  675.         '''Internal: read data in query string format.'''
  676.         qs = self.fp.read(self.length)
  677.         self.list = list = []
  678.         for key, value in parse_qsl(qs, self.keep_blank_values, self.strict_parsing):
  679.             list.append(MiniFieldStorage(key, value))
  680.         
  681.         self.skip_lines()
  682.  
  683.     FieldStorageClass = None
  684.     
  685.     def read_multi(self, environ, keep_blank_values, strict_parsing):
  686.         '''Internal: read a part that is itself multipart.'''
  687.         ib = self.innerboundary
  688.         if not valid_boundary(ib):
  689.             raise ValueError, 'Invalid boundary in multipart form: %r' % (ib,)
  690.         
  691.         self.list = []
  692.         if not self.FieldStorageClass:
  693.             pass
  694.         klass = self.__class__
  695.         part = klass(self.fp, { }, ib, environ, keep_blank_values, strict_parsing)
  696.         while not part.done:
  697.             headers = rfc822.Message(self.fp)
  698.             part = klass(self.fp, headers, ib, environ, keep_blank_values, strict_parsing)
  699.             self.list.append(part)
  700.         self.skip_lines()
  701.  
  702.     
  703.     def read_single(self):
  704.         '''Internal: read an atomic part.'''
  705.         if self.length >= 0:
  706.             self.read_binary()
  707.             self.skip_lines()
  708.         else:
  709.             self.read_lines()
  710.         self.file.seek(0)
  711.  
  712.     bufsize = 8192
  713.     
  714.     def read_binary(self):
  715.         '''Internal: read binary data.'''
  716.         self.file = self.make_file('b')
  717.         todo = self.length
  718.         if todo >= 0:
  719.             while todo > 0:
  720.                 data = self.fp.read(min(todo, self.bufsize))
  721.                 if not data:
  722.                     self.done = -1
  723.                     break
  724.                 
  725.                 self.file.write(data)
  726.                 todo = todo - len(data)
  727.         
  728.  
  729.     
  730.     def read_lines(self):
  731.         '''Internal: read lines until EOF or outerboundary.'''
  732.         self.file = self._FieldStorage__file = StringIO()
  733.         if self.outerboundary:
  734.             self.read_lines_to_outerboundary()
  735.         else:
  736.             self.read_lines_to_eof()
  737.  
  738.     
  739.     def __write(self, line):
  740.         if self._FieldStorage__file is not None:
  741.             if self._FieldStorage__file.tell() + len(line) > 1000:
  742.                 self.file = self.make_file('')
  743.                 self.file.write(self._FieldStorage__file.getvalue())
  744.                 self._FieldStorage__file = None
  745.             
  746.         
  747.         self.file.write(line)
  748.  
  749.     
  750.     def read_lines_to_eof(self):
  751.         '''Internal: read lines until EOF.'''
  752.         while None:
  753.             line = self.fp.readline(65536)
  754.             if not line:
  755.                 self.done = -1
  756.                 break
  757.             
  758.             continue
  759.             return None
  760.  
  761.     
  762.     def read_lines_to_outerboundary(self):
  763.         '''Internal: read lines until outerboundary.'''
  764.         next = '--' + self.outerboundary
  765.         last = next + '--'
  766.         delim = ''
  767.         last_line_lfend = True
  768.         while None:
  769.             line = self.fp.readline(65536)
  770.             if not line:
  771.                 self.done = -1
  772.                 break
  773.             
  774.             if line[:2] == '--' and last_line_lfend:
  775.                 strippedline = line.strip()
  776.                 if strippedline == next:
  777.                     break
  778.                 
  779.                 if strippedline == last:
  780.                     self.done = 1
  781.                     break
  782.                 
  783.             
  784.             odelim = delim
  785.             if line[-2:] == '\r\n':
  786.                 delim = '\r\n'
  787.                 line = line[:-2]
  788.                 last_line_lfend = True
  789.             elif line[-1] == '\n':
  790.                 delim = '\n'
  791.                 line = line[:-1]
  792.                 last_line_lfend = True
  793.             else:
  794.                 delim = ''
  795.                 last_line_lfend = False
  796.             continue
  797.             return None
  798.  
  799.     
  800.     def skip_lines(self):
  801.         '''Internal: skip lines until outer boundary if defined.'''
  802.         if not (self.outerboundary) or self.done:
  803.             return None
  804.         
  805.         next = '--' + self.outerboundary
  806.         last = next + '--'
  807.         last_line_lfend = True
  808.         while None:
  809.             line = self.fp.readline(65536)
  810.             if not line:
  811.                 self.done = -1
  812.                 break
  813.             
  814.             if line[:2] == '--' and last_line_lfend:
  815.                 strippedline = line.strip()
  816.                 if strippedline == next:
  817.                     break
  818.                 
  819.                 if strippedline == last:
  820.                     self.done = 1
  821.                     break
  822.                 
  823.             
  824.             last_line_lfend = line.endswith('\n')
  825.             continue
  826.             return None
  827.  
  828.     
  829.     def make_file(self, binary = None):
  830.         """Overridable: return a readable & writable file.
  831.  
  832.         The file will be used as follows:
  833.         - data is written to it
  834.         - seek(0)
  835.         - data is read from it
  836.  
  837.         The 'binary' argument is unused -- the file is always opened
  838.         in binary mode.
  839.  
  840.         This version opens a temporary file for reading and writing,
  841.         and immediately deletes (unlinks) it.  The trick (on Unix!) is
  842.         that the file can still be used, but it can't be opened by
  843.         another process, and it will automatically be deleted when it
  844.         is closed or when the current process terminates.
  845.  
  846.         If you want a more permanent file, you derive a class which
  847.         overrides this method.  If you want a visible temporary file
  848.         that is nevertheless automatically deleted when the script
  849.         terminates, try defining a __del__ method in a derived class
  850.         which unlinks the temporary files you have created.
  851.  
  852.         """
  853.         import tempfile as tempfile
  854.         return tempfile.TemporaryFile('w+b')
  855.  
  856.  
  857.  
  858. class FormContentDict(UserDict.UserDict):
  859.     '''Form content as dictionary with a list of values per field.
  860.  
  861.     form = FormContentDict()
  862.  
  863.     form[key] -> [value, value, ...]
  864.     key in form -> Boolean
  865.     form.keys() -> [key, key, ...]
  866.     form.values() -> [[val, val, ...], [val, val, ...], ...]
  867.     form.items() ->  [(key, [val, val, ...]), (key, [val, val, ...]), ...]
  868.     form.dict == {key: [val, val, ...], ...}
  869.  
  870.     '''
  871.     
  872.     def __init__(self, environ = os.environ):
  873.         self.dict = self.data = parse(environ = environ)
  874.         self.query_string = environ['QUERY_STRING']
  875.  
  876.  
  877.  
  878. class SvFormContentDict(FormContentDict):
  879.     '''Form content as dictionary expecting a single value per field.
  880.  
  881.     If you only expect a single value for each field, then form[key]
  882.     will return that single value.  It will raise an IndexError if
  883.     that expectation is not true.  If you expect a field to have
  884.     possible multiple values, than you can use form.getlist(key) to
  885.     get all of the values.  values() and items() are a compromise:
  886.     they return single strings where there is a single value, and
  887.     lists of strings otherwise.
  888.  
  889.     '''
  890.     
  891.     def __getitem__(self, key):
  892.         if len(self.dict[key]) > 1:
  893.             raise IndexError, 'expecting a single value'
  894.         
  895.         return self.dict[key][0]
  896.  
  897.     
  898.     def getlist(self, key):
  899.         return self.dict[key]
  900.  
  901.     
  902.     def values(self):
  903.         result = []
  904.         for value in self.dict.values():
  905.             if len(value) == 1:
  906.                 result.append(value[0])
  907.                 continue
  908.             result.append(value)
  909.         
  910.         return result
  911.  
  912.     
  913.     def items(self):
  914.         result = []
  915.         for key, value in self.dict.items():
  916.             if len(value) == 1:
  917.                 result.append((key, value[0]))
  918.                 continue
  919.             result.append((key, value))
  920.         
  921.         return result
  922.  
  923.  
  924.  
  925. class InterpFormContentDict(SvFormContentDict):
  926.     '''This class is present for backwards compatibility only.'''
  927.     
  928.     def __getitem__(self, key):
  929.         v = SvFormContentDict.__getitem__(self, key)
  930.         if v[0] in '0123456789+-.':
  931.             
  932.             try:
  933.                 return int(v)
  934.             except ValueError:
  935.                 
  936.                 try:
  937.                     return float(v)
  938.                 except ValueError:
  939.                     pass
  940.                 except:
  941.                     None<EXCEPTION MATCH>ValueError
  942.                 
  943.  
  944.                 None<EXCEPTION MATCH>ValueError
  945.             
  946.  
  947.         None<EXCEPTION MATCH>ValueError
  948.         return v.strip()
  949.  
  950.     
  951.     def values(self):
  952.         result = []
  953.         for key in self.keys():
  954.             
  955.             try:
  956.                 result.append(self[key])
  957.             continue
  958.             except IndexError:
  959.                 result.append(self.dict[key])
  960.                 continue
  961.             
  962.  
  963.         
  964.         return result
  965.  
  966.     
  967.     def items(self):
  968.         result = []
  969.         for key in self.keys():
  970.             
  971.             try:
  972.                 result.append((key, self[key]))
  973.             continue
  974.             except IndexError:
  975.                 result.append((key, self.dict[key]))
  976.                 continue
  977.             
  978.  
  979.         
  980.         return result
  981.  
  982.  
  983.  
  984. class FormContent(FormContentDict):
  985.     '''This class is present for backwards compatibility only.'''
  986.     
  987.     def values(self, key):
  988.         if key in self.dict:
  989.             return self.dict[key]
  990.         else:
  991.             return None
  992.  
  993.     
  994.     def indexed_value(self, key, location):
  995.         if key in self.dict:
  996.             if len(self.dict[key]) > location:
  997.                 return self.dict[key][location]
  998.             else:
  999.                 return None
  1000.         else:
  1001.             return None
  1002.  
  1003.     
  1004.     def value(self, key):
  1005.         if key in self.dict:
  1006.             return self.dict[key][0]
  1007.         else:
  1008.             return None
  1009.  
  1010.     
  1011.     def length(self, key):
  1012.         return len(self.dict[key])
  1013.  
  1014.     
  1015.     def stripped(self, key):
  1016.         if key in self.dict:
  1017.             return self.dict[key][0].strip()
  1018.         else:
  1019.             return None
  1020.  
  1021.     
  1022.     def pars(self):
  1023.         return self.dict
  1024.  
  1025.  
  1026.  
  1027. def test(environ = os.environ):
  1028.     '''Robust test CGI script, usable as main program.
  1029.  
  1030.     Write minimal HTTP headers and dump all information provided to
  1031.     the script in HTML form.
  1032.  
  1033.     '''
  1034.     global maxlen
  1035.     print 'Content-type: text/html'
  1036.     print 
  1037.     sys.stderr = sys.stdout
  1038.     
  1039.     try:
  1040.         form = FieldStorage()
  1041.         print_directory()
  1042.         print_arguments()
  1043.         print_form(form)
  1044.         print_environ(environ)
  1045.         print_environ_usage()
  1046.         
  1047.         def f():
  1048.             exec 'testing print_exception() -- <I>italics?</I>'
  1049.  
  1050.         
  1051.         def g(f = f):
  1052.             f()
  1053.  
  1054.         print '<H3>What follows is a test, not an actual exception:</H3>'
  1055.         g()
  1056.     except:
  1057.         print_exception()
  1058.  
  1059.     print '<H1>Second try with a small maxlen...</H1>'
  1060.     maxlen = 50
  1061.     
  1062.     try:
  1063.         form = FieldStorage()
  1064.         print_directory()
  1065.         print_arguments()
  1066.         print_form(form)
  1067.         print_environ(environ)
  1068.     except:
  1069.         print_exception()
  1070.  
  1071.  
  1072.  
  1073. def print_exception(type = None, value = None, tb = None, limit = None):
  1074.     if type is None:
  1075.         (type, value, tb) = sys.exc_info()
  1076.     
  1077.     import traceback as traceback
  1078.     print 
  1079.     print '<H3>Traceback (most recent call last):</H3>'
  1080.     list = traceback.format_tb(tb, limit) + traceback.format_exception_only(type, value)
  1081.     print '<PRE>%s<B>%s</B></PRE>' % (escape(''.join(list[:-1])), escape(list[-1]))
  1082.     del tb
  1083.  
  1084.  
  1085. def print_environ(environ = os.environ):
  1086.     '''Dump the shell environment as HTML.'''
  1087.     keys = environ.keys()
  1088.     keys.sort()
  1089.     print 
  1090.     print '<H3>Shell Environment:</H3>'
  1091.     print '<DL>'
  1092.     for key in keys:
  1093.         print '<DT>', escape(key), '<DD>', escape(environ[key])
  1094.     
  1095.     print '</DL>'
  1096.     print 
  1097.  
  1098.  
  1099. def print_form(form):
  1100.     '''Dump the contents of a form as HTML.'''
  1101.     keys = form.keys()
  1102.     keys.sort()
  1103.     print 
  1104.     print '<H3>Form Contents:</H3>'
  1105.     if not keys:
  1106.         print '<P>No form fields.'
  1107.     
  1108.     print '<DL>'
  1109.     for key in keys:
  1110.         print '<DT>' + escape(key) + ':',
  1111.         value = form[key]
  1112.         print '<i>' + escape(repr(type(value))) + '</i>'
  1113.         print '<DD>' + escape(repr(value))
  1114.     
  1115.     print '</DL>'
  1116.     print 
  1117.  
  1118.  
  1119. def print_directory():
  1120.     '''Dump the current directory as HTML.'''
  1121.     print 
  1122.     print '<H3>Current Working Directory:</H3>'
  1123.     
  1124.     try:
  1125.         pwd = os.getcwd()
  1126.     except os.error:
  1127.         msg = None
  1128.         print 'os.error:', escape(str(msg))
  1129.  
  1130.     print escape(pwd)
  1131.     print 
  1132.  
  1133.  
  1134. def print_arguments():
  1135.     print 
  1136.     print '<H3>Command Line Arguments:</H3>'
  1137.     print 
  1138.     print sys.argv
  1139.     print 
  1140.  
  1141.  
  1142. def print_environ_usage():
  1143.     '''Dump a list of environment variables used by CGI as HTML.'''
  1144.     print '\n<H3>These environment variables could have been set:</H3>\n<UL>\n<LI>AUTH_TYPE\n<LI>CONTENT_LENGTH\n<LI>CONTENT_TYPE\n<LI>DATE_GMT\n<LI>DATE_LOCAL\n<LI>DOCUMENT_NAME\n<LI>DOCUMENT_ROOT\n<LI>DOCUMENT_URI\n<LI>GATEWAY_INTERFACE\n<LI>LAST_MODIFIED\n<LI>PATH\n<LI>PATH_INFO\n<LI>PATH_TRANSLATED\n<LI>QUERY_STRING\n<LI>REMOTE_ADDR\n<LI>REMOTE_HOST\n<LI>REMOTE_IDENT\n<LI>REMOTE_USER\n<LI>REQUEST_METHOD\n<LI>SCRIPT_NAME\n<LI>SERVER_NAME\n<LI>SERVER_PORT\n<LI>SERVER_PROTOCOL\n<LI>SERVER_ROOT\n<LI>SERVER_SOFTWARE\n</UL>\nIn addition, HTTP headers sent by the server may be passed in the\nenvironment as well.  Here are some common variable names:\n<UL>\n<LI>HTTP_ACCEPT\n<LI>HTTP_CONNECTION\n<LI>HTTP_HOST\n<LI>HTTP_PRAGMA\n<LI>HTTP_REFERER\n<LI>HTTP_USER_AGENT\n</UL>\n'
  1145.  
  1146.  
  1147. def escape(s, quote = None):
  1148.     '''Replace special characters "&", "<" and ">" to HTML-safe sequences.
  1149.     If the optional flag quote is true, the quotation mark character (")
  1150.     is also translated.'''
  1151.     s = s.replace('&', '&')
  1152.     s = s.replace('<', '<')
  1153.     s = s.replace('>', '>')
  1154.     if quote:
  1155.         s = s.replace('"', '"')
  1156.     
  1157.     return s
  1158.  
  1159.  
  1160. def valid_boundary(s, _vb_pattern = '^[ -~]{0,200}[!-~]$'):
  1161.     import re as re
  1162.     return re.match(_vb_pattern, s)
  1163.  
  1164. if __name__ == '__main__':
  1165.     test()
  1166.  
  1167.